<template>
  <m-modal
    :visible="visible"
    mask
    resizable
    :title="title"
    size="small"
    :showFooter="true"
    cancelText="取 消"
    okText="确 定"
    :width="width || 400"
    :height="height || 400"
    @ok="handleSave"
    @cancel="handleCancel"
  >
    <div class="v-value-editor-modal">
      <div
        ref="left"
        class="left"
        @mousedown="handleOperate(false)"
      >
        <div
          v-for="(item, index) in inputs"
          :key="item.id"
          class="row-value"
        >
          <div
            v-if="isHtmlTextProperty && (item.value as string).startsWith('<')"
            style="width: 100%"
            class="_input"
            :class="{ 'selected-item': index === focusIndex }"
            @click="handleFocus(index)"
          >
            <HTMLViewer
              :htmlText="(item.value as string)"
              :projectId="getProjectId()"
              @click.prevent
            />
          </div>
          <div
            v-else
            style="width: 100%"
          >
            <!-- 当一个元素的 pointer-events 属性设置为 none 时，该元素不会成为鼠标事件的目标，鼠标事件会像该元素不存在一样传递到下面的元素。 -->
            <el-input-number
              v-if="isNumberType && (typeof item.value === 'number' || item.value === undefined || item.value === null)"
              v-model="item.value"
              :controls="false"
              style="width: 100%"
              :step-strictly="stepStrictly"
              :min="minNum"
              :max="999999999"
              @focus="handleFocus(index)"
            />

            <el-input
              v-else
              v-model="item.value"
              :class="{ 'selected-item': index === focusIndex }"
              class="string-input _input"
              type="textarea"
              maxlength="200"
              @focus="handleFocus(index)"
              @input="val => handleInputChange(val, index)"
              @blur="handleBlur"
            />
          </div>
          <div
            v-if="dataType === PropertyDataType.STRING"
            class="g-pd-r-4 img-btn"
            @click="handleClick(index)"
          >
            <img
              src="statics/icons/app/iconmore.png"
              class="g-pointer"
            />
          </div>
        </div>
      </div>
      <div
        class="_input-rows-operation-btns g-flex-0 g-lh-14 g-pd-4"
        @mousedown="handleOperate(true)"
      >
        <div>
          <div>
            <img
              src="statics/icons/propertyOperation/iconadd.png"
              class="g-pointer"
              @click="handleAdd"
            />
          </div>
          <div
            class="g-m-t-4"
            :class="{ disabled: isInputEmpty || isUnselected }"
          >
            <img
              src="statics/icons/propertyOperation/iconreduce.png"
              class="g-pointer"
              @click="handleDelete"
            />
          </div>
          <div
            class="g-m-t-4"
            :class="{ disabled: isInputEmpty || focusIndex === 0 || isUnselected }"
          >
            <img
              src="statics/icons/propertyOperation/iconup.png"
              class="g-pointer"
              @click="handleUp"
            />
          </div>
          <div
            class="g-m-t-4"
            :class="{ disabled: isInputEmpty || focusIndex === inputs.length - 1 || isUnselected }"
          >
            <img
              src="statics/icons/propertyOperation/icondown.png"
              class="g-pointer"
              @click="handleDown"
            />
          </div>
        </div>
      </div>
    </div>
  </m-modal>
</template>

<script setup lang="ts">
import { usePortal } from "@/common/usePortal";
import { mixPopup } from "@/common/Portal";
import { computed, nextTick, onMounted, reactive, ref } from "vue";
import { getUid } from "@/util/common";
import { EditorOperateType } from "../common/ValueSpecificationTypes";
import { htmlEditorWindow } from "@/modules/model/modals/htmlEditor";
import { PropertyDataType } from "@/constants/Enums";
import HTMLViewer from "@/modules/model/comps/common/HTMLViewer.vue";
defineOptions(
  mixPopup({
    name: "value-editor-modal"
  })
);
const props = defineProps<{
  inputItems: { value?: string | number; id: string }[];
  title: string;
  operateType: EditorOperateType;
  dataType: PropertyDataType;
  isHtmlTextProperty?: boolean;
  width?: number;
  height?: number;
  autofocusIndex?: number /** 默认聚焦 序号 */;
  modelId?: string;
}>();

const emit = defineEmits<{
  (event: "sure", data: any): void;
  (event: "close", data: any): void;
}>();

const { visible, handleOk, handleCancel } = usePortal(emit);
const focusIndex = ref(props.autofocusIndex || 0);

const inputType = computed(() => {
  switch (props.dataType) {
    case PropertyDataType.INTEGER:
    case PropertyDataType.REAL:
    case PropertyDataType.UNLIMITEDNATURAL:
      return "number";

    default:
      return "text";
  }
});

const stepStrictly = computed(() => {
  return props.dataType !== PropertyDataType.REAL;
});

const inputs = reactive(
  props.inputItems.map(item => {
    return {
      ...item,
      value: inputType.value === "number" ? item.value && Number(item.value) : item.value
    };
  })
);

const left = ref<HTMLElement | null>(null);
const isInputEmpty = computed(() => inputs.length === 0);
const isUnselected = computed(() => focusIndex.value === -1);
const isOperateClick = ref(false);

const minNum = computed(() => {
  if (props.dataType === PropertyDataType.UNLIMITEDNATURAL) {
    return 0;
  }
  return -999999999;
});

const isNumberType = computed(() => {
  return inputType.value === "number";
});

async function handleClick(index: number) {
  const item = inputs[index];
  isOperateClick.value = true;
  focusIndex.value = index;
  await htmlEditorWindow
    .popup({
      projectId: app.activeProject?.id || "",
      text: encodeURIComponent(item.value || ""),
      modelId: props.modelId || ""
    })
    .then(async res => {
      if (res.success) {
        inputs[index].value = res.value as string;
      }
    })
    .catch((err: any) => err && console.error(err));
}

function handleOperate(value: boolean) {
  isOperateClick.value = value;
}

function createEmptyValue() {
  return {
    value: isNumberType.value ? undefined : "",
    id: getUid()
  };
}
const handleSave = () => {
  handleOk(inputs);
};
const handleInputChange = (val: string, index: number) => {
  inputs[index].value = val;
};

function autoFocus() {
  nextTick(() => {
    if (left.value) {
      const focusInputContainer = left.value.children[focusIndex.value];
      let focusInput = focusInputContainer?.querySelector("input");
      if (focusInput && focusInput.tagName === "INPUT") {
        focusInput.focus();
      }
    }
  });
}
function handleFocus(index: number) {
  focusIndex.value = index;
}
function handleBlur() {
  if (isOperateClick.value) {
    isOperateClick.value = false;
    return;
  }
  focusIndex.value = -1;
}
function handleAdd() {
  const emptyValue = createEmptyValue();
  if (isUnselected.value || inputs.length === 0) {
    inputs.push(emptyValue);
    focusIndex.value = inputs.length - 1;
  } else {
    inputs.splice(focusIndex.value + 1, 0, emptyValue);
    focusIndex.value++;
  }
  autoFocus();
}

function handleDelete() {
  if (inputs.length === 0 || isUnselected.value) {
    return;
  }
  const index = focusIndex.value;
  inputs.splice(index, 1);
  /** 若删除的是最后一条,选中前一条 */
  if (index === inputs.length) {
    focusIndex.value--;
  }
  autoFocus();
}

function handleUp() {
  const curIndex = focusIndex.value;
  if (curIndex === 0 || isInputEmpty.value || isUnselected.value) return;
  const curInput = inputs[curIndex];
  inputs[curIndex] = inputs[curIndex - 1];
  inputs[curIndex - 1] = curInput;
  focusIndex.value--;
  autoFocus();
}

function handleDown() {
  const curIndex = focusIndex.value;
  if (curIndex === inputs.length - 1 || isInputEmpty.value || isUnselected.value) return;
  const curInput = inputs[curIndex];
  inputs[curIndex] = inputs[curIndex + 1];
  inputs[curIndex + 1] = curInput;
  focusIndex.value++;
  autoFocus();
}

const getProjectId = () => app.activeProject?.id || "";

onMounted(() => {
  /** 如果是新增类型则添加一条新记录 */
  if (props.operateType === EditorOperateType.ADD) {
    inputs.push(createEmptyValue());
    focusIndex.value = inputs.length - 1;
  }
  autoFocus();
});
</script>

<style lang="scss">
.v-value-editor-modal {
  display: flex;
  height: 100%;
  .left {
    flex: 1;
    border-right: 1px solid #eee;
    overflow-y: auto;
    .row-value {
      display: flex;
      align-items: center;
      margin-top: 2px;
    }
    .selected-item {
      border: 1px solid rgb(39, 39, 207);
    }
  }
  ._input-rows-operation-btns {
    flex-shrink: 0;
  }
  ._input {
    width: 100%;
    margin: 2px 0;
    text-indent: 3px;
    outline: none;
    overflow: hidden;
    border: none;
  }
  .string-input {
    border: 1px solid #eee;
    line-height: 22px;
  }
  .img-btn {
    align-self: flex-end;
    vertical-align: baseline;
  }
  .disabled {
    opacity: 0.5; /* 降低不透明度来表示禁用 */
    /* 或者应用灰色滤镜效果 */
    filter: grayscale(100%);
  }
  .el-input-number,
  .el-input-number.is-without-controls {
    .el-input__wrapper {
      padding-left: 3px;
    }
    .el-input__inner {
      text-align: left;
    }
  }
}
</style>
